package com.thinkit.cms.service.model;

import cn.hutool.core.io.FileUtil;
import com.google.common.collect.Lists;
import com.thinkit.cms.api.model.ModelLoopHelp;
import com.thinkit.cms.api.model.ModelService;
import com.thinkit.cms.api.model.ModelTemplateService;
import com.thinkit.cms.api.site.SiteTemplateService;
import com.thinkit.cms.dto.model.FieldDto;
import com.thinkit.cms.dto.model.ModelDto;
import com.thinkit.cms.dto.model.ModelTemplateDto;
import com.thinkit.cms.dto.site.SiteTemplateDto;
import com.thinkit.cms.entity.model.Model;
import com.thinkit.cms.mapper.model.ModelMapper;
import com.thinkit.core.annotation.SiteMark;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.core.constant.Constants;
import com.thinkit.utils.enums.SiteOperation;
import com.thinkit.utils.model.KeyValueModel;
import com.thinkit.utils.model.PageDto;
import com.thinkit.utils.model.TreeFileModel;
import com.thinkit.utils.properties.ThinkItProperties;
import com.thinkit.utils.utils.Checker;
import com.thinkit.utils.utils.FileLoopUtil;
import com.thinkit.utils.utils.Md5;
import com.thinkit.utils.utils.ModelFieldUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author LG
 * @since 2019-10-23
 */
@Service
public class ModelServiceImpl extends BaseServiceImpl<FieldDto, Model, ModelMapper> implements ModelService {

    @Autowired
    ThinkItProperties thinkItProperties;

    @Autowired
    SiteTemplateService siteTemplateService;

    @Autowired
    ModelTemplateService modelTemplateService;

    @SiteMark(type = SiteOperation.READ)
    @Override
    public PageDto<FieldDto> listPage(PageDto<FieldDto> d) {
        getSiteId(true);
        return super.listPage(d);
    }

    @Transactional
    @SiteMark
    @Override
    public void saveModel(FieldDto v) {
        ModelFieldUtil.filter(v);
        v.setId(id());
        super.insert(v);
        saveModelTemplate(v);
    }

    private void saveModelTemplate(FieldDto v){
        modelTemplateService.saveModelTemp(v.getId(),getSiteId(),v.getTemplateId(),v.getTemplatePath().replace("\\","/"));
    }

    @Transactional
    @SiteMark
    @CacheEvict(value = Constants.cacheName, key = "#root.targetClass+'.getByPk.'+#p0.id")
    @Override
    public void updateModel(FieldDto v) {
        ModelFieldUtil.filter(v);
        super.updateByPk(v);
        String templateId = siteTemplateService.findTemplateId(getSiteId());
        ModelTemplateDto modelTemplateDto = modelTemplateService.getModelTemplate(v.getId(),templateId,getSiteId());
        if(Checker.BeNotNull(modelTemplateDto)){
            modelTemplateDto.setTemplatePath(v.getTemplatePath().replace("\\","/"));
            modelTemplateService.updateByPk(modelTemplateDto);
        }else{
            saveModelTemplate(v);
        }
    }

    @Override
    public List<TreeFileModel> loadTemplateTree() {
        String tempath = siteTemplateService.findTemplatePath(getSiteId());
        if(Checker.BeBlank(tempath) || !FileUtil.exist(tempath)){
            return Lists.newArrayList();
        }
        List<TreeFileModel> treeFileModels=FileLoopUtil.loopLoadFiles(tempath,thinkItProperties.getTemplate(),new ModelLoopHelp());
        return treeFileModels;
    }

    private SiteTemplateDto loadDefaultTemplate(){
        return  siteTemplateService.findTemplate(getSiteId());
    }

    @Override
    public Map<String, Object> loadTemplate() {
        Map<String,Object> result = new HashMap<>();
        result.put("templateFiles",loadTemplateTree());
        SiteTemplateDto siteTemplateDto = loadDefaultTemplate();
        if(Checker.BeNotNull(siteTemplateDto)){
            result.put("templateId",siteTemplateDto.getTemplateId());
        }
        return result;
    }

    @Override
    public FieldDto getById(String pk) {
        SiteTemplateDto siteTemplateDto= siteTemplateService.findTemplate(getSiteId());
        FieldDto modelDto =super.getByPk(pk);
        if(Checker.BeNotNull(modelDto)){
           ModelTemplateDto modelTemplateDto = modelTemplateService.getModelTemplate(modelDto.getId(),siteTemplateDto.getTemplateId(),getSiteId());
           if(Checker.BeNotNull(modelTemplateDto)){
               modelDto.setModelTemplateId(modelTemplateDto.getId()).setTemplateId(modelTemplateDto.getTemplateId());
               String filePath = thinkItProperties.getTemplate()+modelTemplateDto.getTemplatePath();
               if(FileUtil.exist(filePath) && FileUtil.isFile(filePath)){
                   modelDto.setMd5Key(Md5.md5(new File(filePath).getAbsolutePath().replace("\\","/"))).
                   setTemplatePath(modelTemplateDto.getTemplatePath());
               }
           }
        }
        return modelDto;
    }

    @Override
    public List<ModelDto> listModel(String categoryId) {
         String templateId = siteTemplateService.findTemplateId(getSiteId());
         List<Model> models = baseMapper.listModelByCategoryId(getSiteId(),categoryId,templateId);
         if(Checker.BeNotEmpty(models)){
             for(Model model:models){
                 if(Checker.BeNotBlank(model.getTemplatePath())){
                     String filePath =thinkItProperties.getTemplate()+model.getTemplatePath();
                     if(FileUtil.exist(filePath)){
                         model.setMd5Key(Md5.md5(new File(filePath).getAbsolutePath().replace("\\","/")));
                     }
                 }
             }
         }
         return Checker.BeNotEmpty(models)?O2CS(models,ModelDto.class):Lists.newArrayList();
    }


    @Override
    public List<KeyValueModel> listPublihModel(String categoryId) {
        String templateId = siteTemplateService.findTemplateId(getSiteId());
        List<KeyValueModel> keyValueModels =baseMapper.listPublihModel(categoryId,getSiteId(),templateId);
        return Checker.BeNotEmpty(keyValueModels)?keyValueModels:Lists.newArrayList();
    }

    @Override
    public String getFormDesign(String modelId) {
        String fieldDesignStr =baseMapper.getFormDesign(modelId);
        return fieldDesignStr;
    }

    @Override
    public Boolean getFormHasfile(String modelId) {
        Boolean hasFile = baseMapper.getFormHasfile(modelId);
        return hasFile;
    }

    @Override
    public ModelDto getModel(String modelId) {
        Model model = baseMapper.getModel(modelId);
        return O2C(model,ModelDto.class);
    }
}
